﻿using System;
using System.Linq;
using ForumsBrowser.BusinessObjects;
using Timer = System.Threading.Timer;
using TimerCallback = System.Threading.TimerCallback;
using System.Collections.Generic;

namespace ForumsBrowser.ObjectGateway
{
    internal class ForumUpdater
    {

        private EventHandler<ForumUpdateEventArgs> _update;

        private object _eventLock = new object();
        private static object m_lock = new object();

        public event EventHandler<ForumUpdateEventArgs> Update
        { 
            add 
            {
                lock (_eventLock)
                {
                    _update -= value; _update += value;
                }
            }
            remove
            {
                lock (_eventLock)
                {
                    _update -= value;
                }
            }
        }


        private static List<ForumUpdater> _updaters = new List<ForumUpdater>();
        private static Timer _timer;
        private string _forumShortName;
        private DateTime? _lastUpdate;
        private EventHandler<ForumUpdateEventArgs> _subscriptionMethod;

        static ForumUpdater()
        {
            lock (m_lock)
            {
                _timer = new Timer(onTick, null, 30000, 30000);
            }
        }

        internal ForumUpdater(string shortName, EventHandler<ForumUpdateEventArgs> subscriptionMethod)
        {
            if (!_updaters.Any(f => f._forumShortName == shortName))
            {
                _forumShortName = shortName;
                _subscriptionMethod = subscriptionMethod;
                Update += _subscriptionMethod;
                _updaters.Add(this);
                new Action(onTick).BeginInvoke(null, null);
            }
        }

        private static void onTick(object value)
        {
            _updaters.ForEach(u => u.onTick());
        }

        private void onTick()
        {
            var forum = Gateway.ForumGet(_forumShortName, _lastUpdate);
            if (forum != null)
            {
                SetLastUpdated(forum);
                OnUpdate(forum);
            }
        }

        private void OnUpdate(Forum forum)
        {
            var args = new ForumUpdateEventArgs { Forum = forum };
            var handler = _update;
            if (handler != null)
                handler(null, args);
        }

        private void SetLastUpdated(Forum input)
        {
            // Update the _lastUpdated time. 
            var dates = input.Threads.Select(m => m.LastUpdate);
            if (dates.Any())
                _lastUpdate = dates.Max().ToUniversalTime().AddSeconds(1);
        }

        internal static void StopUpdates(string forumName)
        {
            var updater = _updaters.First(u => u._forumShortName == forumName);
            updater.Update -= updater._subscriptionMethod;
            if (updater != null) _updaters.Remove(updater);
        }
    }
}
